package com.iot.manage.biz.controller;

import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

import java.util.Date;
import java.util.List;

import javax.validation.Valid;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import com.iot.common.core.exception.AuthorizationException;
import com.iot.common.core.exception.ModelException;
import com.iot.common.core.util.R;
import com.iot.common.core.util.UuidUtil;
import com.iot.common.security.annotation.SecurityAuthorization;
import com.iot.common.security.domain.SimpleUser;
import com.iot.common.security.util.SecurityUtils;
import com.iot.manage.api.domain.SysMenu;
import com.iot.manage.api.domain.SysOrg;
import com.iot.manage.api.domain.SysRole;
import com.iot.manage.api.domain.SysUser;
import com.iot.manage.api.domain.SysUserOrg;
import com.iot.manage.api.domain.SysUserRole;
import com.iot.manage.biz.service.SysUserService;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;

@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
@Api(value = "user", tags = "用户管理模块")
public class UserController {

	@Setter
	private Throwable cause;

	private final SysUserService userService;

	/**
	 * 获取当前用户全部信息
	 * 
	 * @return 用户信息
	 * @throws Exception
	 */
	@SecurityAuthorization
	@GetMapping(value = { "/info" }, produces = "application/json; charset=utf-8")
	public R<SysUser> info() throws Exception {
		SimpleUser simpleUser = SecurityUtils.getUser();
		if (simpleUser == null) {
			throw new AuthorizationException("请先登录！");
		}
		return userService.info(simpleUser.getId());
	}

	@SecurityAuthorization
	@GetMapping(value = { "/getUserMenus" }, produces = "application/json; charset=utf-8")
	public R<List<SysMenu>> getUserMenus() throws Exception {
		SimpleUser simpleUser = SecurityUtils.getUser();
		if (simpleUser == null) {
			throw new AuthorizationException("请先登录！");
		}
		return userService.getUserMenus(simpleUser.getId(),"0");
	}

	@GetMapping("/info/{username}")
	public R<SysUser> info(@PathVariable String username) {
		return userService.loadUserByUsername(username);
	}

	@SecurityAuthorization
	@GetMapping(value = { "/list" }, produces = "application/json; charset=utf-8")
	public R<Page<SysUser>> list(@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "orgId", required = false, defaultValue = "") String orgId,
			@RequestParam(name = "status", required = false, defaultValue = "") String status,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit) throws Exception {
		String sqlExceptSelect = " FROM " + SysUser.TABLE_NAME + " o  WHERE 1=1 ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' OR   O.USERNAME LIKE '%" + keywords + "%' ) ";
		}
		if (!StrKit.isBlank(orgId)) {
			sqlExceptSelect += " AND O.ID IN ( SELECT USERID FROM "+SysUserOrg.TABLE_NAME+" WHERE  ORGID='"+orgId+"') ";
		}
		if (!StrKit.isBlank(status)) {
			sqlExceptSelect += " AND O.ISLOCK='"+status+"' ";
		}
		sqlExceptSelect += "  ORDER BY   O.UPDATE_TIME desc ";

		Page<SysUser> pages = SysUser.dao.paginate(cur, limit, "select * ", sqlExceptSelect);

		if (pages != null && pages.getList() != null && pages.getList().size() > 0) {
			List<SysOrg> orgs;
			String orgName = "";
			List<SysRole> roles;
			String roleName = "";
			for (SysUser user : pages.getList()) {
				orgs = SysOrg.dao.find("select name from " + SysOrg.TABLE_NAME + " where id in (select orgId from "
						+ SysUserOrg.TABLE_NAME + " where userId=? ) ", user.getId());
				if (orgs != null && orgs.size() > 0) {
					orgName = "";
					for (SysOrg org : orgs) {
						orgName += org.getName() + "|";
					}
					user.setOrgName(orgName.substring(0, orgName.length() - 1));
				}
				roles = SysRole.dao.find("select name from " + SysRole.TABLE_NAME + " where id in (select role_id from "
						+ SysUserRole.TABLE_NAME + " where user_id=? ) ", user.getId());
				if (roles != null && roles.size() > 0) {
					roleName = "";
					for (SysRole role : roles) {
						roleName += role.getName() + "|";
					}
					user.setRoleName(roleName.substring(0, roleName.length() - 1));
				}
			}
		}
		return R.ok(pages);
	}

	@SecurityAuthorization
	@PostMapping(value = { "/deleteById" }, produces = "application/json; charset=utf-8")
	public R<Boolean> deleteById(@RequestParam(name = "id", required = true) String id) throws Exception {
		if (SysUser.dao.deleteById(id)) {
			return R.ok(true);
		} else {
			return R.failed(false);
		}
	}

	@SecurityAuthorization
	@PostMapping(value = { "/resetPassword" }, produces = "application/json; charset=utf-8")
	public R<Boolean> resetPassword(@RequestParam(name = "id", required = true) String id) throws Exception {
		SysUser sysUser = SysUser.dao.findById(id);
		if (sysUser == null) {
			throw new Exception("密码重置失败，用户已不存在！");
		}
		sysUser.setPassword(ENCODER.encode(sysUser.getUsername() + "@123456"));
		if (!sysUser.update()) {
			throw new Exception("密码重置失败！");
		}
		return R.ok();
	}

	@SecurityAuthorization
	@PostMapping(value = { "/deleteUsers" }, produces = "application/json; charset=utf-8")
	public R<Boolean> deleteUsers(@RequestParam(name = "ids", required = true) String ids) throws Exception {

		String[] userIds = ids.split(",");
		for (String id : userIds) {
			if (!StrKit.isBlank(id) && !StrKit.equals(id, "1")) {
				if (!SysUser.dao.deleteById(id)) {
					throw new Exception("批量删除用户失败！");
				}
			}
		}
		return R.ok(true);
	}

	private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

	@SecurityAuthorization
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public R<SysRole> save(@Valid SysUser sysUser) {
		if (sysUser == null) {
			throw new ModelException("用户对象不可以为空！");
		}
		if (StrKit.isBlank(sysUser.getId())) {
			sysUser.setId(UuidUtil.getUUID());
			sysUser.setPassword(ENCODER.encode(sysUser.getUsername() + "@123456"));
			sysUser.setCreateTime(new Date(System.currentTimeMillis()));
			if (sysUser.save()) {
				return R.ok();
			}
		} else {
			if (sysUser.update()) {
				return R.ok();
			}
		}
		return R.failed();
	}

	@SecurityAuthorization
	@RequestMapping(value = "/getUserOrgTree", method = RequestMethod.GET)
	public R<List<SysOrg>> getUserOrgTree(@RequestParam(name = "userId", required = false) String userId) {
		return R.ok(userService.getUserOrgs(userId));
	}

	@SecurityAuthorization
	@GetMapping(value = { "/getUserRoles" }, produces = "application/json; charset=utf-8")
	public R<Page<SysRole>> getUserRoles(
			@RequestParam(name = "keywords", required = false, defaultValue = "") String keywords,
			@RequestParam(name = "cur", required = false, defaultValue = "1") int cur,
			@RequestParam(name = "limit", required = false, defaultValue = "10") int limit,
			@RequestParam(name = "userId", required = false, defaultValue = "") String userId,
			@RequestParam(name = "status", required = false, defaultValue = "") String status) throws Exception {

		String sqlExceptSelect = " FROM " + SysRole.TABLE_NAME + " O  WHERE 1=1 ";
		if (!StrKit.isBlank(keywords)) {
			sqlExceptSelect += " AND ( O.NAME LIKE '%" + keywords + "%' OR   O.CODE LIKE '%" + keywords + "%' ) ";
		}
		if (!StrKit.isBlank(status)) {
			if(StrKit.equals("1", status))
				sqlExceptSelect += " AND O.ID IN ( SELECT ROLE_ID FROM "+ SysUserRole.TABLE_NAME+" WHERE  USER_ID='"+userId+"' ) ";
			else {
				sqlExceptSelect += " AND O.ID NOT IN ( SELECT ROLE_ID FROM "+ SysUserRole.TABLE_NAME+" WHERE  USER_ID='"+userId+"' ) ";
			}
		}
		sqlExceptSelect += "  ORDER BY   O.UPDATETIME desc ";
		return R.ok(SysRole.dao.paginate(cur, limit,
				"select O.* ",
				sqlExceptSelect));
	}
	

	@SecurityAuthorization
	@PostMapping(value = { "/saveUserOrgs" }, produces = "application/json; charset=utf-8")
	public R<Boolean> saveUserOrgs(@RequestParam(name = "orgIds", required = false) String orgIds,@RequestParam(name = "userId", required = true) String userId) throws Exception {
		SysUserOrg sysUserOrg;
		String[] ids = orgIds.split(",");
		StringBuffer sb=new StringBuffer();
		for (String orgId : ids) {
			if (!StrKit.isBlank(orgId)) {
				sysUserOrg=SysUserOrg.dao.findByIds(userId,orgId);
				if(sysUserOrg==null) {
					sysUserOrg =new SysUserOrg();
					sysUserOrg.setOrgId(orgId);
					sysUserOrg.setUserId(userId);
					if(!sysUserOrg.save()) {
						throw new Exception("保存用户组织机构授权失败！");
					}
				}
				sb.append("'").append(orgId).append("'").append(",");
			}
		}
		if(!StrKit.isBlank(sb.toString())) {
			Db.delete("delete from "+SysUserOrg.TABLE_NAME+" where orgId not in ("+sb.substring(0, sb.length()-1)+") and userId=? ",userId);
			return R.ok("用户组织机构授权成功！",true);
		}else {
			int i=Db.delete("delete from "+SysUserOrg.TABLE_NAME+" where userId=? ",userId);
			if(i>0) {
				return R.ok("用户组织机构授权已经取消！",true);
			}else {
				return R.warn("未变更组织机构授权！",false);
			}
		}
		
	}
	
	
	@SecurityAuthorization
	@PostMapping(value = { "/saveUserRoles" }, produces = "application/json; charset=utf-8")
	public R<Boolean> saveUserRoles(@RequestParam(name = "roleIds", required = false) String roleIds,
			@RequestParam(name = "userId", required = true) String userId,@RequestParam(name = "status", required = false) String status) throws Exception {
		SysUserRole sysUserRole;
		String[] ids = roleIds.split(",");
		for (String roleId : ids) {
			if (!StrKit.isBlank(roleId)) {
				sysUserRole=SysUserRole.dao.findByIds(userId,roleId);
				if(StrKit.equals("0",status)) {
					if(sysUserRole==null) {
						sysUserRole =new SysUserRole();
						sysUserRole.setRoleId(roleId);
						sysUserRole.setUserId(userId);
						if(!sysUserRole.save()) {
							throw new Exception("保存分配角色失败！");
						}
					}
				}else {
					if(sysUserRole!=null) {
						if(!sysUserRole.delete()) {
							throw new Exception("取消角色失败！");
						}
					}
				}
			}
		}
		if(StrKit.equals("0",status)) {
			return R.ok("分配角色成功！",true);
		}else {
			return R.ok("角色已取消！",true);
		}
	}
	
	

}
